package com.jreiffers.uihandlers;

import java.lang.reflect.Method;

import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

/**
 * The event types supported by UiHandler.
 * 
 * @author johannes
 * 
 */
public enum EventType {

	LISTENER_EVENT(new IEventListenerAdapter() {

		@Override
		public Object adapt(final Object o, final Method m) {
			return new Listener() {

				@Override
				public void handleEvent(Event event) {
					invokeHandler(o, m, event);
				}
				
			};
		}
		
	}, "addListener", Listener.class, Event.class, DummyHint.class),
	
	PAINT_CONTROL(new IEventListenerAdapter() {

		@Override
		public Object adapt(final Object o, final Method m) {
			return new PaintListener() {

				@Override
				public void paintControl(PaintEvent e) {
					invokeHandler(o, m, e);
				}
				
			};
		}
		
	}, "addPaintListener", PaintListener.class, PaintEvent.class, null),
	
	MOUSE_UP(new IEventListenerAdapter() {
		
		@Override
		public Object adapt(final Object o, final Method m) {	
			return new MouseAdapter() {
				
				@Override
				public void mouseUp(MouseEvent e) {
					invokeHandler(o, m, e);
				}
				
			};
		}
	}, "addMouseListener", MouseListener.class, MouseEvent.class, EventHints.MouseUp.class),
	
	DROP(new IEventListenerAdapter() {

		@Override
		public Object adapt(final Object o, final Method m) {
			return new DropTargetAdapter() {
				
				@Override
				public void drop(DropTargetEvent e) {
					invokeHandler(o, m, e);
				}

			};
		}
		
		
	}, "addDropListener", DropTargetListener.class, DropTargetEvent.class, null)
	
	;

	private interface DummyHint extends EventHints {}
	
	public final IEventListenerAdapter adapter;
	public final String methodName;
	public final Class<?> methodParam;
	public final Class<?> paramClass;
	public final Class<?> hint;

	/**
	 * 
	 * @param adapter
	 *            the adapter that converts a Method into an EventListener.
	 * @param methodName
	 *            the name of the method to use for adding the adapted
	 *            EventListener
	 * @param methodParam
	 *            the class of the parameter of the method methodName
	 * @param paramClass
	 *            the class of the parameter of the Method that is being
	 *            converted
	 */
	private EventType(IEventListenerAdapter adapter, String methodName, Class<?> methodParam,
			Class<?> paramClass, Class<?> hintClass) {
		this.adapter = adapter;
		this.methodName = methodName;
		this.methodParam = methodParam;
		this.paramClass = paramClass;
		this.hint = hintClass == null ? EventHints.class : hintClass;
	}

	private static void invokeHandler(final Object o, final Method m, Object event) {
		try {
			m.invoke(o, event);
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

}
